﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Input;
using TaskManagerApp.Common;
using TaskManagerApp.Model;

namespace TaskManagerApp.ViewModel
{
    public class TaskViewModel : WorkspaceViewModel, IDataErrorInfo
    {
                #region Fields

        ITask task;
        readonly ITaskRepository taskRepository;
        string[] taskTypeOptions;
        bool isSelected;
        RelayCommand saveCommand;

        #endregion // Fields

        #region Constructor

        public TaskViewModel(ITask task, ITaskRepository taskRepository)
        {
            if (task == null)
                throw new ArgumentNullException("task");

            if (taskRepository == null)
                throw new ArgumentNullException("taskRepository");

            setTask(task);
            this.taskRepository = taskRepository;
        }

        private void setTask(ITask task)
        {
            this.task = task;
            Description = task.Description;
            Start = task.Start;
            End = task.End;
            TaskType = task.TaskType;
        }

        #endregion // Constructor

        #region Task Properties

        public string Description
        {
            get { return task.Description; }
            set
            {
                if (value == task.Description)
                    return;

                task.Description = value;

                base.OnPropertyChanged("Description");
            }
        }

        public DateTime Start
        {
            get { return task.Start; }
            set
            {
                if (value == task.Start)
                    return;

                task.Start = value;

                base.OnPropertyChanged("Start");
            }
        }

        public DateTime End
        {
            get { return task.End; }
            set
            {
                if (value == task.End)
                    return;

                task.End = value;

                base.OnPropertyChanged("End");
            }
        }

        public string TaskType
        {
            get { return task.TaskType; }
            set
            {
                if (value == task.TaskType)
                    return;

                if (value != null)
                {
                    task.TaskType = value;

                    base.OnPropertyChanged("TaskType");
                }
            }
        }


        #endregion // Tasks Properties

        /// <summary>
        /// Gets/sets whether this task is selected in the UI.
        /// </summary>
        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                if (value == isSelected)
                    return;

                isSelected = value;

                base.OnPropertyChanged("IsSelected");
            }
        }


        /// <summary>
        /// Returns a list of strings used to populate the Task Type selector.
        /// </summary>
        public string[] TaskTypeOptions
        {
            get
            {
                if (taskTypeOptions == null)
                {
                    taskTypeOptions = new string[]
                    {
                        Strings.TaskViewModel_TaskType_General,
                        Strings.TaskViewModel_TaskType_Business,
                        Strings.TaskViewModel_TaskType_NonBusiness
                    };
                }

                return taskTypeOptions;
            }
        }

        public override string DisplayName
        {
            get
            {
                if (this.IsNewTask)
                {
                    return Strings.TaskViewModel_DisplayName;
                }
                else
                {
                    return String.Format("{0}", task.Description);
                }
            }
        }

        private bool IsNewTask
        {
            get { return (!taskRepository.ContainsTask(task)); }
        }

        /// <summary>
        /// Returns a command that saves the Task.
        /// </summary>
        public ICommand SaveCommand
        {
            get
            {
                if (saveCommand == null)
                {
                    saveCommand = new RelayCommand(
                        param => this.Save(),
                        param => this.CanSave
                        );
                }
                return saveCommand;
            }
        }

        /// <summary>
        /// Returns true if the Task is valid and can be saved.
        /// </summary>
        bool CanSave
        {
            get { return task.IsValid; }
        }

        private void Save()
        {
            if (!task.IsValid)
                throw new InvalidOperationException(Errors.TaskViewModel_Exception_CannotSave);

            if (this.IsNewTask)
                taskRepository.AddTask(task);


            ITask tmptask = Task.CreateTask();
            setTask(tmptask);

        }

        #region IDataErrorInfo Members

        string IDataErrorInfo.Error
        {
            get { return (task as IDataErrorInfo).Error; }
        }

        string IDataErrorInfo.this[string propertyName]
        {
            get
            {
                string error = null;
                error = (task as IDataErrorInfo)[propertyName];
                // Dirty the commands registered with CommandManager,
                // such as our Save command, so that they are queried
                // to see if they can execute now.
                CommandManager.InvalidateRequerySuggested();

                return error;
            }
        }

        #endregion // IDataErrorInfo Members

    }
}
